package compiler;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import descriptors.AbstractDescr;
import nodes.AbstractNode;

public class Compiler {
	
	private int address = 0;
	private int level=0;
	private int label=0;
	private FileWriter writer;
	private final AbstractNode tree;
	
	public Compiler(AbstractNode tree,FileWriter writer){
		this.tree=tree;
		this.writer=writer;
	}
	
	public SymbolTable compile() throws IOException{
		SymbolTable st=new SymbolTable(this);
		tree.compile(st, this);
		writer.close();
		return st;
	}

	public int newLabel() {
		return label++;
	}
	
	public int level(){
		return level;
	}
	
	public void incLevel(){
		level++;
	}
	
	public void decLevel(){
		level--;
	}

	public void setAddress(int address){
		this.address=address;
	}
	
	public int allocateMem(AbstractDescr descr){
		int result=address;
		address+=descr.getSize();
		return result;
	}
	
	public int allocateMem(int size){
		int result=address;
		address+=size;
		return result;
	}
	
	public int address(){
		return address;
	}
	
	public void write(String operation) {
		try {
			System.out.println("Writing " + operation);
			writer.write(operation + System.getProperty("line.separator"));
			writer.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
  
	}
	
	public static void main(String[] argv){
		List<Yytoken> list=new LinkedList<Yytoken>();
		if (argv.length < 2) {
			System.out.println("Usage : java Compiler <inputfile> <outputfile>");
		} else {
			try {
				String infile = argv[0];
				Scanner scanner = new Scanner(new java.io.FileReader(infile));
				Yytoken token=scanner.yylex();
				while(token!=null){
					if(token!=null){
						list.add(token);
					}
					token=scanner.yylex();
				}
				list.add(new Yytoken("Last","Last",-1,-1));
				
			} catch (java.io.FileNotFoundException e) {
				System.out.println("File not found : \"" + argv[0] + "\"");
			} catch (Exception e) {
				System.out.println("Unexpected exception:");
				e.printStackTrace();
			}
			System.out.println("\n===============");
			System.out.println("Starting Parser");
			System.out.println("===============\n");
			Parser parser=new Parser(list);
			AbstractNode module=parser.parse();
			System.out.println("\n===============");
			System.out.println("AST");
			System.out.println("===============\n");
			module.print();
			System.out.println("\n===============");
			System.out.println("Starting compiler");
			System.out.println("===============\n");
			File output = new File(argv[1]);
			try{
				Compiler compiler=new Compiler(module,new FileWriter(output));
				SymbolTable st=compiler.compile();
				System.out.println("\n===============");
				System.out.println("Result: SymbolTable");
				System.out.println("===============\n");
				st.print();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
}
